package com.demo.controller.admin;

import com.demo.dao.MessageDao;
import com.demo.dao.UserDao;
import com.demo.entity.Message;
import com.demo.entity.User;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
@Transactional

class AdminMessageControllerIT {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private MessageDao messageDao;

    @Autowired
    private UserDao userDao;

    private final int PAGE_SIZE = 10;
    private final int TOTAL_MESSAGES = 207;

    private int TOTAL_MESSAGES_STATE1 = 0;
    private int TOTAL_MESSAGES_STATE2 = 0;
    private int TOTAL_MESSAGES_STATE3 = 0;

    private final int TOTAL_USERS = 5;
    private List<Integer> generatedMessageIds = new ArrayList<>();

    @BeforeEach
    void setUp() {
        // 清空并初始化测试数据
        messageDao.deleteAll();
        userDao.deleteAll();

        LocalDateTime baseTime = LocalDateTime.now();

        // 1. 插入用户测试数据
        IntStream.rangeClosed(1, TOTAL_USERS).forEach(i -> {
            User user = new User(
                    i,
                    "testUser" + i,
                    "用户" + i,
                    "password" + i,
                    "user" + i + "@example.com",
                    "1380013800" + i,
                    i == 1 ? 1 : 0, // 第一个用户是管理员
                    "/images/avatar" + i + ".jpg"
            );
            userDao.save(user);
        });

        // 2. 插入消息测试数据（关联用户）
        IntStream.rangeClosed(1, TOTAL_MESSAGES).forEach(i -> {
            String userID = "testUser" + ((i % TOTAL_USERS) + 1); // 循环分配用户
            Message message = new Message(
                    0,
                    userID,
                    "消息内容" + i,
                    baseTime.minusDays(TOTAL_MESSAGES - i),
                    i % 3 + 1 // 状态1,2,3循环
            );
            switch (i%3 + 1){
                case 1:TOTAL_MESSAGES_STATE1 ++;break;
                case 2:TOTAL_MESSAGES_STATE2 ++;break;
                case 3:TOTAL_MESSAGES_STATE3 ++;break;
                default:break;
            }
            messageDao.save(message);
        });
        // 添加验证
        long count = messageDao.count();
        for( Message m : messageDao.findAll()){
            System.out.println(m);
            generatedMessageIds.add(m.getMessageID());
        }
        System.out.println("Inserted messages count: " + count);
        assertTrue(count > 0, "测试数据未正确插入");
    }

    @Test
    void messageList_ShouldReturnPaginatedResults() throws Exception {
        mockMvc.perform(get("/messageList.do").param("page", "1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$").isArray())
                .andExpect(jsonPath("$.length()").value(PAGE_SIZE));
    }

    @Test
    void messageList_ShouldReturnPaginatedResultsLastPage() throws Exception {
        mockMvc.perform(get("/messageList.do").param("page", String.valueOf(TOTAL_MESSAGES_STATE1 / PAGE_SIZE + 1)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$").isArray())
                .andExpect(jsonPath("$.length()").value(TOTAL_MESSAGES_STATE1%PAGE_SIZE));
    }

    @Test
    void adminOperations_ShouldRequireAdminRole() throws Exception {
        // 测试管理员权限验证
        mockMvc.perform(post("/passMessage.do").param("messageID", String.valueOf(generatedMessageIds.get(0))))
                .andExpect(status().isUnauthorized()); // 或根据您的权限设计返回特定状态码
    }

    @Test
    void messageWithUserInfo_ShouldContainUserDetails() throws Exception {
        // 验证返回的消息包含用户信息
        mockMvc.perform(get("/messageList.do"))
                .andExpect(jsonPath("$[0].userName").exists())
                .andExpect(jsonPath("$[0].picture").exists());
    }
    @Test
    void messageList_ShouldReturnPaginatedResultsFromDatabase() throws Exception {
        // 执行请求并验证
        mockMvc.perform(get("/messageList.do").param("page", "1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$").isArray())
                .andExpect(jsonPath("$.length()").value(PAGE_SIZE));
    }

    @Test
    void passMessage_ShouldUpdateStateInDatabase() throws Exception {
        int messageId = generatedMessageIds.get(0);

        mockMvc.perform(post("/passMessage.do")
                        .param("messageID", String.valueOf(messageId)))
                .andExpect(status().isOk())
                .andExpect(content().string("true"));

        // 验证数据库状态
        Message updated = messageDao.findByMessageID(messageId);
        assertEquals(2, updated.getState()); // 2表示审核通过
    }

    @Test
    void rejectMessage_ShouldUpdateStateInDatabase() throws Exception {
        int messageId = generatedMessageIds.get(1);

        mockMvc.perform(post("/rejectMessage.do")
                        .param("messageID", String.valueOf(messageId)))
                .andExpect(status().isOk())
                .andExpect(content().string("true"));

        // 验证数据库状态
        Message updated = messageDao.findByMessageID(messageId);
        assertEquals(3, updated.getState()); // 3表示拒绝
    }

    @Test
    void messageManage_ShouldCountPendingMessages() throws Exception {
        long pendingCount = messageDao.findAllByState(1, PageRequest.of(0, 1))
                .getTotalElements();

        mockMvc.perform(get("/message_manage"))
                .andExpect(status().isOk())
                .andExpect(model().attributeExists("total"))
                .andExpect(model().attribute("total", (int) Math.ceil((double) pendingCount / PAGE_SIZE)));
    }

    @Test
    void messageList_ShouldFilterByState() throws Exception {
        // 确保只返回state=1的待审核消息
        mockMvc.perform(get("/messageList.do"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[?(@.state != 1)]").doesNotExist());
    }
}
